﻿/*
 * Twipler - Twitter Web Client with features.
 *  
 *  Copyright (C) 2009, 2010. Ian Quigley
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details. 
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Caching;
using NHibernate.Mapping;
using Twipler.App.Parse.Code;
using Twipler.App.DataDoc;
using Dimebrain.TweetSharp.Fluent;
using Twipler.Data.Cache;
using Twipler.Xtensions;

namespace Twipler.App.Entity
{
    public class Users : ICallableClass
    {
        public static IDataDoc ShowProfileFor(string screenname)
        {
            return Current.SessionTrack.ApiCaller.Request(t => t.Users().ShowProfileFor(screenname.ToLower()), false);
        }

        public static IDataDoc GetFollowers(string screenname)
        {
            return Current.SessionTrack.ApiCaller.Request(t => t.Users().GetFollowers().For(screenname.ToLower()).CreateCursor(), true);
        }

		public static IDataDoc GetFriends(string screenname)
		{
			return Current.SessionTrack.ApiCaller.Request(t => t.Users().GetFriends().For(screenname.ToLower()).CreateCursor(), true);
		}

        public static IDataDoc GetMutualFollowers(string screenname, int page, int count)
		{
			// Get their friends 
            string response = Current.SessionTrack.ApiCaller.RequestRaw(t => t.SocialGraph().Ids().ForFriendsOf(screenname.ToLower()), true);
			if ((response == null) || (response.IndexOf("error") != -1))
				return new DataDocList(DataDocStatus.TwiplerError, "Could not retrieve friends for user.");

			// Get my friends
			List<Friend> myFriends = TableStore<Friend>.Open(Current.Visitor.Id).ReadAll();

			// Get the mutual
			IEnumerable<int> mutuals = from mine in myFriends
			                          join their in response.AsJsonList(str => { int i; int.TryParse(str, out i); return i; }) on mine.Id equals their
			                          select mine.Id;

			DataDocList results = new DataDocList();

            if (mutuals.Count() == 0)
            {
                results.Add(new DataDocValue("", null));
                return results;
            }

            if (mutuals.Count() > count)
                mutuals = mutuals.Skip(page * count).Take(count);

			int index = 0;
			
			using (TableStore<TwitterUserDetails> twitterUsers = TableStore<TwitterUserDetails>.Open())
			{
                List<DataDocValue> list = new List<DataDocValue>();

				foreach (int mutual in mutuals)
				{
					TwitterUserDetails mutualFriend = twitterUsers.Find(mutual);
					if (mutualFriend == null)
						continue;

					List<DataDocValue> mutualDoc = new List<DataDocValue>();
					mutualDoc.Add(new DataDocValue("twitter_id", mutualFriend.Id));
					mutualDoc.Add(new DataDocValue("screen_name", mutualFriend.ScreenName));
					mutualDoc.Add(new DataDocValue("profile_image_url", mutualFriend.ProfileImageUrl));

					list.Add(new DataDocValue( index.ToString(), mutualDoc));
					index++;
				}

                results.Add("", list);
			}
				
			return results;
		}

        public static string ScreenNameLike(string partMatch)
        {
            if (partMatch.StartsWith("@"))
                partMatch = partMatch.Substring(1);

        	partMatch = partMatch.ToLower();

            IEnumerable<string> ppl = Current.SessionTrack.ScreenNames;

            if (ppl == null || !ppl.Any())
                return string.Empty;

            string name = ppl.First();
            int closest = name.LevenshteinDistance(partMatch);

            foreach (string peep in ppl)
            {
                string peeppart = peep;
                if (peeppart.Length > partMatch.Length)
                    peeppart = peeppart.Substring(0, partMatch.Length);

                int ld = peeppart.ToLower().LevenshteinDistance(partMatch);
                if (ld < closest)
                {
                    closest = ld;
                    name = peep;
                }
            }

            return name;
        }
	}
}
